/*
 * This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3
 * http://www.gnu.org/licenses/lgpl-3.0.html
 */

#ifndef CBPLUGIN_H
#define CBPLUGIN_H

#include <wx/arrstr.h>
#include <wx/event.h>
#include <wx/intl.h>
#include <wx/string.h>

#include "settings.h" // build settings
#include "globals.h"
#include "logger.h"
#include "manager.h"
#include "pluginmanager.h"
#include "prep.h"

#ifdef __WXMSW__
    #ifndef PLUGIN_EXPORT
        #ifdef EXPORT_LIB
            #define PLUGIN_EXPORT __declspec (dllexport)
        #else // !EXPORT_LIB
            #ifdef BUILDING_PLUGIN
                #define PLUGIN_EXPORT __declspec (dllexport)
            #else // !BUILDING_PLUGIN
                #define PLUGIN_EXPORT __declspec (dllimport)
            #endif // BUILDING_PLUGIN
        #endif // EXPORT_LIB
    #endif // PLUGIN_EXPORT
#else
    #define PLUGIN_EXPORT
#endif

// this is the plugins SDK version number
// it will change when the SDK interface breaks
//
// 这是插件的SDK版本号,当SDK接口中断时,它将更改此版本号
//
#define PLUGIN_SDK_VERSION_MAJOR   1
#define PLUGIN_SDK_VERSION_MINOR   33
#define PLUGIN_SDK_VERSION_RELEASE 0

// class decls
// 声明类
class wxMenuBar;
class wxMenu;
class wxToolBar;
class wxPanel;
class wxWindow;

class cbBreakpoint;
class cbConfigurationPanel;
class cbDebuggerConfiguration;
class cbEditor;
class cbProject;
class cbStackFrame;
class cbStatusBar;
class cbThread;
class cbWatch;
class Compiler;
class CompileTargetBase;
class ConfigManagerWrapper;
class FileTreeData;
class ProjectBuildTarget;

struct PluginInfo;

// Define basic groups for plugins' configuration.
// 定义插件配置的基本组.

///< Compiler related.
///< 与编译器相关.
static const int cgCompiler         = 0x01;
///< Editor related.
///< 与编辑器相关
static const int cgEditor           = 0x02;
///< One of the core plugins.
///< 核心插件之一.
static const int cgCorePlugin       = 0x04;
///< One of the contrib plugins (or any third-party plugin for that matter).
///< 一个分发插件(contrib)插件(或任何第三方插件).
static const int cgContribPlugin    = 0x08;
///< Unknown. This will be probably grouped with cgContribPlugin.
///< 未知.这可能与cgContribPlugin组合在一起.
static const int cgUnknown          = 0x10;

/**
 * 实现功能: Base class for plugins
  *
  * This is the most basic class a plugin must descend
  * from.
  * cbPlugin descends from wxEvtHandler, so it provides its methods as well...
  * \n \n
  * It's not enough to create a new plugin. You must also provide a resource
  * zip file containing a file named "manifest.xml". Check the manifest.xml
  * file of existing plugins to see how to create one (it's ultra-simple).
  *
  * 实现功能:插件的基类.
  * 这是插件必须继承的最基本的类.
  * cbPlugin是wxEvtHandler的后代,所以它也提供了它的方法...
  * 仅仅创建一个新插件是不够的.还必须提供包含名为"manifest.xml"的文件的资源zip文件.
  * 检查现有插件的manifest.xml文件,看看如何创建一个插件(非常简单).
  */
class PLUGIN_EXPORT cbPlugin : public wxEvtHandler
{
    public:
        /** In default cbPlugin's constructor the associated PluginInfo structure
          * is filled with default values. If you inherit from cbPlugin, you
          * should fill the m_PluginInfo members with the appropriate values.
          *
          * 在默认cbPlugin的构造函数中,关联的PluginInfo结构用默认值填充.
          * 如果从cbPlugin继承,则应使用适当的值填充m_PluginInfo成员.
          */
        cbPlugin();

        /**
         * cbPlugin destructor.
         * 析构函数
         */
        virtual ~cbPlugin();

        /**
         * The plugin must return its type on request.
         *
         * 插件必须根据请求返回其类型.
         */
        virtual PluginType GetType() const { return m_Type; }

        /**
         * Return the plugin's configuration priority.
          * This is a number (default is 50) that is used to sort plugins
          * in configuration dialogs. Lower numbers mean the plugin's
          * configuration is put higher in the list.
          *
          * 返回插件的配置优先级.
          * 这是一个数字(默认为50),用于对配置对话框中的插件进行排序.
          * 数字越低,说明插件的配置在列表中的位置越高.
          *
          */
        virtual int GetConfigurationPriority() const { return 50; }

        /**
         * Return the configuration group for this plugin. Default is cgUnknown.
          * Notice that you can logically AND more than one configuration groups,
          * so you could set it, for example, as "cgCompiler | cgContribPlugin".
          *
          * 返回此插件的配置组.默认值为cgUnknown.
          * 注意,您可以在逻辑上设置多个配置组,因此可以将其设置为"cgCompiler | cgContribPlugin".
          *
          */
        virtual int GetConfigurationGroup() const { return cgUnknown; }

        /**
         * Return plugin's configuration panel.
          * 参数说明: parent The parent window.
          * 返回值:  A pointer to the plugin's cbConfigurationPanel. It is deleted by the caller.
          *
          * 返回插件的配置面板.
          * 参数说明: parent 父窗口.
          * 返回值:指向插件的cbConfigurationPanel的指针.它被调用方删除.
          */
        virtual cbConfigurationPanel* GetConfigurationPanel(cb_optional wxWindow* parent){ return nullptr; }

        /**
         * Return plugin's configuration panel for projects.
          * The panel returned from this function will be added in the project's
          * configuration dialog.
          * 参数说明: parent The parent window.
          * 参数说明: project The project that is being edited.
          * 返回值:  A pointer to the plugin's cbConfigurationPanel. It is deleted by the caller.
          *
          * 返回插件的项目配置面板.
          * 此函数返回的面板将添加到项目的配置对话框中.
          * 参数说明: parent 父窗口.
          * 参数说明: project 正在编辑的项目.
          * 返回值:  指向插件的cbConfigurationPanel的指针.它被调用方删除.
          *
          */
        virtual cbConfigurationPanel* GetProjectConfigurationPanel(cb_optional wxWindow* parent, cb_optional cbProject* project){ return nullptr; }

        /** This method is called by Code::Blocks and is used by the plugin
          * to add any menu items it needs on Code::Blocks's menu bar.\n
          * It is a pure virtual method that needs to be implemented by all
          * plugins. If the plugin does not need to add items on the menu,
          * just do nothing ;)
          *
          * 注释: This function may be called more than one time. This can happen,
          * for example, when a plugin is installed or uninstalled.
          *
          * 参数说明: menuBar the wxMenuBar to create items in
          *
          * 此方法由Code::Blocks调用,
          * 插件使用此方法在Code::Blocks的菜单栏上添加所需的任何菜单项.
          * 它是纯虚拟方法,需要由所有插件实现.
          * 如果插件不需要在菜单上添加项,则不必执行任何操作.
          *
          * 注释:此函数可能被多次调用.例如,在安装或卸载插件时,可能会发生这种情况.
          * 参数说明: menuBar 要在中创建项的wxMenuBar
          *
          */
        virtual void BuildMenu(cb_optional wxMenuBar* menuBar) {}

    /**
     * This method is called by Code::Blocks core modules (EditorManager,
      * ProjectManager etc) and is used by the plugin to add any menu
      * items it needs in the module's popup menu. For example, when
      * the user right-clicks on a project file in the project tree,
      * ProjectManager prepares a popup menu to display with context
      * sensitive options for that file. Before it displays this popup
      * menu, it asks all attached plugins (by asking PluginManager to call
      * this method), if they need to add any entries
      * in that menu. This method is called.\n
      * If the plugin does not need to add items in the menu,
      * just do nothing ;)
      * 参数说明: type the module that's preparing a popup menu
      * 参数说明: menu pointer to the popup menu
      * 参数说明: data pointer to FileTreeData object (to access/modify the file tree)
      *
      * 此方法由Code::Blocks核心模块(EditorManager,ProjectManager等)调用,
      * 插件使用此方法在模块的弹出菜单中添加所需的任何菜单项.
      * 例如,当用户右键单击项目树中的项目文件时,ProjectManager会准备一个弹出菜单,显示该文件的上下文相关选项.
      * 在显示这个弹出菜单之前,它会询问所有附加的插件(通过让PluginManager调用这个方法),
      * 如果它们需要在菜单中添加任何条目.此方法被调用.
      * 如果插件不需要在菜单中添加项,则不必执行任何操作
      *
      * 参数说明: type 准备弹出菜单的模块.
      * 参数说明: menu 指向弹出菜单的指针
      * 参数说明: data 指向FileTreeData对象的指针(用于访问/修改文件树)
      *
      */
        virtual void BuildModuleMenu(cb_optional const ModuleType type, cb_optional wxMenu* menu, cb_optional const FileTreeData* data = nullptr) { }

        /**
         * This method is called by Code::Blocks and is used by the plugin
          * to add any toolbar items it needs on Code::Blocks's toolbar.\n
          * It is a pure virtual method that needs to be implemented by all
          * plugins. If the plugin does not need to add items on the toolbar,
          * just do nothing ;)
          * 参数说明: toolBar the wxToolBar to create items on
          * 返回值:  The plugin should return true if it needed the toolbar, false if not
          *
          * 此方法由Code::Blocks调用,插件使用此方法在Code::Blocks的工具栏上添加所需的任何工具栏项.
          * 它是一个纯虚拟方法,需要由所有插件实现.
          * 如果插件不需要在工具栏上添加项,则不必执行任何操作
          *
          * 参数说明: toolBar 要在其上创建项的wxToolBar
          * 返回值:  如果插件需要工具栏,它应该返回true否则返回false
          *
          */
        virtual bool BuildToolBar(cb_optional wxToolBar* toolBar ) { return false; }

        /**
         * This method return the priority of the plugin's toolbar, the less value
          * indicates a more preceding position when C::B starts with no configuration file
          *
          * 此方法返回插件工具栏的优先级,值越小表示C::B在没有配置文件的情况下开始时的位置越靠前.
          *
          */
        virtual int GetToolBarPriority() { return 50; }

#if wxUSE_STATUSBAR
        /**
         * This method is called by Code::Blocks and is used by the plugin
          * to add a field on Code::Blocks's statusbar.\n
          * If the plugin does not need to add items on the statusbar, just
          * do nothing ;)
          * 参数说明: statusBar the cbStatusBar to create items on
          *
          * 此方法由Code::Blocks调用,插件使用此方法在Code::Blocks的状态栏上添加字段.
          * 如果插件不需要在statusbar上添加项,则不必执行任何操作.
          *
          * 参数说明: statusBar 要在其上创建项的cbStatusBar
          *
          */
        virtual void CreateStatusField(cbStatusBar *statusBar) { wxUnusedVar(statusBar); }
#endif

        /**
         * See whether this plugin is attached or not. A plugin should not perform
          * any of its tasks, if not attached...
          * 注释: This function is *not* virtual.
          * 返回值:  Returns true if it attached, false if not.
          *
          * 看看这个插件是否已连接.插件不应该执行任何任务,如果没有附加...
          *
          * 注释:这个函数不是虚拟的.
          * 返回值: 附加时返回true,不附加时返回false.
          *
          */
        bool IsAttached() const { return m_IsAttached; }

        /**
         * See whether this plugin can be detached (unloaded) or not.
          * This function is called usually when the user requests to
          * uninstall or disable a plugin. Before disabling/uninstalling it, Code::Blocks
          * asks the plugin if it can be detached or not. In other words, it checks
          * to see if it can be disabled/uninstalled safely...
          * @par
          * A plugin should return true if it can be detached at this moment, false if not.
          * 返回值:  The default implementation returns true.
          *
          * 看看这个插件是否可以被分离(卸载).
          * 此函数通常在用户请求卸载或禁用插件时调用.
          * 在禁用/卸载插件之前,Code::Blocks会询问插件是否可以分离.
          * 换句话说,它会检查是否可以安全地禁用/卸载...
          * 如果此时可以分离插件,则插件应返回true,否则返回false.
          *
          * 返回值:  默认实现返回true.
          *
          */
        virtual bool CanDetach() const { return true; }
    protected:
        /**
         * Any descendent plugin should override this virtual method and
          * perform any necessary initialization. This method is called by
          * Code::Blocks (PluginManager actually) when the plugin has been
          * loaded and should attach in Code::Blocks. When Code::Blocks
          * starts up, it finds and <em>loads</em> all plugins but <em>does
          * not</em> activate (attaches) them. It then activates all plugins
          * that the user has selected to be activated on start-up.\n
          * This means that a plugin might be loaded but <b>not</b> activated...\n
          * Think of this method as the actual constructor...
          *
          * 任何子插件都应重写此虚拟方法并执行任何必要的初始化.
          * 当插件已经加载并且应该附加在Code::Blocks中时,此方法由Code::Blocks(实际上是PluginManager)调用.
          * 当Code::Blocks启动时,它会查找并加载所有插件,但不会激活(附加)它们.
          * 然后激活用户选择在启动时激活的所有插件.
          * 这意味着插件可能已加载但未激活...
          * 将此方法视为实际的构造函数...
          *
          */
        virtual void OnAttach(){}

        /**
         * Any descendent plugin should override this virtual method and
          * perform any necessary de-initialization. This method is called by
          * Code::Blocks (PluginManager actually) when the plugin has been
          * loaded, attached and should de-attach from Code::Blocks.\n
          * Think of this method as the actual destructor...
          * 参数说明: appShutDown If true, the application is shutting down. In this
          *         case *don't* use Manager::Get()->Get...() functions or the
          *         behaviour is undefined...
          *
          * 任何子插件都应重写此虚拟方法并执行任何必要的取消初始化.
          * 当插件已经加载,附加并且应该从Code::Blocks取消附加时,
          * Code::Blocks(实际上是PluginManager)调用此方法.
          * 把这个方法想象成真正的析构函数...
          *
          * 参数说明: appShutDown如果为true,则应用程序正在关闭.
          * 在这种情况下,不要使用Manager::Get()->Get...()函数或行为未定义...
          *
          */
        virtual void OnRelease(cb_optional bool appShutDown){}

        /**
         * This method logs a "Not implemented" message and is provided for
          * convenience only.
          *
          * 此方法记录"未实现"消息,仅为方便起见而提供.
          *
          */
        virtual void NotImplemented(const wxString& log) const;

        /**
         * Holds the plugin's type. Set in the default constructor.
         * 保存插件的类型.在默认构造函数中设置.
         */
        PluginType m_Type;

        /**
         * Holds the "attached" state.
         * 保持"附加"状态.
         */
        bool m_IsAttached;

    private:

        // only the plugin manager has access here
        // 只有插件管理器可以访问这里
        friend class PluginManager;

        /**
         * Attach is <b>not</b> a virtual function, so you can't override it.
          * The default implementation hooks the plugin to Code::Block's
          * event handling system, so that the plugin can receive (and process)
          * events from Code::Blocks core library. Use OnAttach() for any
          * initialization specific tasks.
          * @see OnAttach()
          *
          * Attach不是虚拟函数,因此不能重写它.
          * 默认实现将插件挂接到Code::Block的事件处理系统,
          * 以便插件可以从Code::Blocks核心库接收(和处理)事件.
          * 对任何特定于初始化的任务使用OnAttach().
          * 参考OnAttach()
          */
        void Attach();

        /** Release is <b>not</b> a virtual function, so you can't override it.
          * The default implementation un-hooks the plugin from Code::Blocks's
          * event handling system. Use OnRelease() for any clean-up specific
          * tasks.
          * 参数说明: appShutDown If true, the application is shutting down. In this
          *         case *don't* use Manager::Get()->Get...() functions or the
          *         behaviour is undefined...
          * @see OnRelease()
          *
          * Release不是虚拟函数,因此不能重写它.
          * 默认实现从Code::Blocks的事件处理系统中取消挂接插件.
          * 使用OnRelease()执行任何清理特定任务.
          *
          * 参数说明: appShutDown如果为true,则应用程序正在关闭.在这种情况下,不要使用Manager::Get()->Get...()函数或行为未定义...
          *
          * 参考:OnRelease()
          *
          */
        void Release(bool appShutDown);
};

/**
* 实现功能: Base class for compiler plugins
* This plugin type must offer some pre-defined build facilities, on top
* of the generic plugin's.
*
* 实现功能: 编译器插件基类
* 这个插件类型必须在通用插件的基础上提供一些预定义的构建工具.
*/
class PLUGIN_EXPORT cbCompilerPlugin: public cbPlugin {
public:
    cbCompilerPlugin();

    /**
     * 实现功能: Run the project/target.          *
      * Running a project means executing its build output. Of course
      * this depends on the selected build target and its type.          *
      * 参数说明: target The specific build target to "run". If NULL, the plugin
      * should ask the user which target to "run" (except maybe if there is
      * only one build target in the project).
      *
      * 实现功能: 运行项目/目标.
      * 运行项目意味着执行其构建输出.当然,这取决于所选的构建目标及其类型.
      * 参数说明:target 要"运行"的特定构建目标.如果为空,插件应该询问用户要"运行"哪个目标(除非项目中只有一个生成目标).
      *
      */
    virtual int Run(ProjectBuildTarget *target = nullptr) = 0;

    /**
     * Same as Run(ProjectBuildTarget*) but with a wxString argument.
     * 与Run(ProjectBuildTarget*)相同,但具有wxString参数
     */
    virtual int Run(const wxString &target) = 0;

    /**
     * 实现功能: Clean the project/target.
      * Cleaning a project means deleting any files created by building it.
      * This includes any object files, the binary output file, etc.
      * 参数说明: target The specific build target to "clean". If NULL, it
      * cleans all the build targets of the current project.
      *
      * 实现功能: 清理项目/目标.清除项目意味着删除通过生成项目而创建的任何文件.这包括任何对象文件,二进制输出文件等.
      * 参数说明: target 要“清除”的特定生成目标.如果为空,则清除当前项目的所有生成目标.
      */
    virtual int Clean(ProjectBuildTarget *target = nullptr) = 0;

    /**
     * Same as Clean(ProjectBuildTarget*) but with a wxString argument.
     * 与Clean(ProjectBuildTarget*)相同,但使用wxString参数.
     */
    virtual int Clean(const wxString &target) = 0;

    /**
     * 实现功能: DistClean the project/target.
      * DistClean will typically remove any config files
      * and anything else that got created as part of
      * building a software package.
      * 参数说明: target The specific build target to "distclean". If NULL, it
      * cleans all the build targets of the current project.
      *
      * 实现功能: 使用(DistClean)清理项目/目标.DistClean通常会删除任何配置文件以及在构建软件包时创建的任何其他文件.
      * 参数说明: target "distclean"的特定生成目标.如果为空,则清除当前项目的所有生成目标.
      */
    virtual int DistClean(ProjectBuildTarget *target = nullptr) = 0;

    /**
     * Same as DistClean(ProjectBuildTarget*) but with a wxString argument.
     * 与DistClean(ProjectBuildTarget*)相同,但使用wxString参数.
     */
    virtual int DistClean(const wxString &target) = 0;

    /**
     * 实现功能: Build the project/target.
      * 参数说明: target The specific build target to build. If NULL, it
      * builds all the targets of the current project.
      *
      * 实现功能:构建项目/目标.
      * 参数说明: target 要生成的特定生成目标.如果为空,则生成当前项目的所有目标.
      */
    virtual int Build(ProjectBuildTarget *target = nullptr) = 0;

    /**
     * Same as Build(ProjectBuildTarget*) but with a wxString argument.
     * 与Build(ProjectBuildTarget*)相同,但具有wxString参数.
     * */
    virtual int Build(const wxString &target) = 0;

    /**
     * 实现功能: Rebuild the project/target.
      * Rebuilding a project is equal to calling Clean() and then Build().
      * This makes sure that all compilable files in the project will be
      * compiled again.
      * 参数说明: target The specific build target to rebuild. If NULL, it
      * rebuilds all the build targets of the current project.
      *
     * 实现功能: 重新构建项目/目标.重建项目等于调用Clean()然后再调用Build().这将确保再次编译项目中的所有可编译文件.
      * 参数说明: target 要重新构建的特定生成目标.如果为空,则重新构建当前项目的所有生成目标.
      */
    virtual int Rebuild(ProjectBuildTarget *target = nullptr) = 0;

    /**
     * Same as Rebuild(ProjectBuildTarget*) but with a wxString argument.
     * 与Rebuild(ProjectBuildTarget*)相同,但使用wxString参数.
     */
    virtual int Rebuild(const wxString &target) = 0;

    /**
     * 实现功能: Build all open projects.
      * 参数说明: target If not empty, the target to build in each project. Else all targets.
      *
     * 实现功能: 构建所有打开的项目.
      * 参数说明: target 如果不为空,则为要在每个项目中生成的目标.否则所有目标.
      */
    virtual int BuildWorkspace(const wxString &target = wxEmptyString) = 0;

    /**
     * 实现功能: Rebuild all open projects.
      * 参数说明: target If not empty, the target to rebuild in each project. Else all targets.
      *
     * 实现功能: 重新构建所有打开的项目.
      * 参数说明: target 如果不为空,则为要在每个项目中重新构建的目标.否则所有目标.
      */
    virtual int RebuildWorkspace(const wxString &target = wxEmptyString) = 0;

    /**
     * 实现功能: Clean all open projects.
      * 参数说明: target If not empty, the target to clean in each project. Else all targets.
      *
       * 实现功能: 清理所有打开的项目.
      * 参数说明: target 如果不为空,则在每个项目中清除的目标.否则所有目标.

      */
    virtual int CleanWorkspace(const wxString &target = wxEmptyString) = 0;

    /**
     * 实现功能: Compile a specific file.
      * 参数说明: file The file to compile (must be a project file!)
      *
       * 实现功能: 编译一个特定的文件.
      * 参数说明: file 要编译的文件(必须是项目文件!)

      */
    virtual int CompileFile(const wxString &file) = 0;

    /**
     * 实现功能: Abort the current build process.
     * 实现功能: 中止当前构建过程
     * */
    virtual int KillProcess() = 0;

    /**
     * 实现功能: Is the plugin currently compiling?
     * 实现功能:插件当前正在编译?
     * */
    virtual bool IsRunning() const = 0;

    /**
     * 实现功能: Get the exit code of the last build process.
     * 实现功能: 获取上一个生成进程的退出代码.
     */
    virtual int GetExitCode() const = 0;

    /**
     * 实现功能: Display configuration dialog.
      * 参数说明: project The selected project (can be NULL).
      * 参数说明: target The selected target (can be NULL).
      *
       * 实现功能: 显示配置对话框.
      * 参数说明: project 所选项目(可以为空).
      * 参数说明: target 所选目标(可以为空).

      */
    virtual int Configure(cbProject *project, ProjectBuildTarget *target = nullptr) = 0;

private:
};

//闪烁事件类
class wxScintillaEvent;
//调试器功能枚举结构
struct cbDebuggerFeature
{
    enum Flags
    {
        Breakpoints,
        Callstack,
        CPURegisters,
        Disassembly,
        ExamineMemory,
        Threads,
        Watches,
        ValueTooltips,
        RunToCursor,
        SetNextStatement
    };
};

/**
* 实现功能: Base class for debugger plugins
* This plugin type must offer some pre-defined debug facilities, on top
* of the generic plugin's.
*
* 实现功能: 调试器插件的基类.此插件类型必须在通用插件的基础上提供一些预定义的调试工具.
*/
class PLUGIN_EXPORT cbDebuggerPlugin: public cbPlugin
{
    public:
        cbDebuggerPlugin(const wxString& guiName, const wxString& settingsName);

    public:
        virtual void OnAttach();
        virtual void OnRelease(bool appShutDown);

        virtual void BuildMenu(wxMenuBar* menuBar);
        virtual void BuildModuleMenu(const ModuleType type, wxMenu* menu, const FileTreeData* data = nullptr);
        virtual bool BuildToolBar(wxToolBar* toolBar);

        /**
          * 实现功能: Notify the debugger that lines were added or removed in an editor.
          * This causes the debugger to keep the breakpoints list in-sync with the
          * editors (i.e. what the user sees).
          * 参数说明: editor The editor in question.
          * 参数说明: startline The starting line this change took place.
          * 参数说明: lines The number of lines added or removed. If it's a positive number,
          *              lines were added. If it's a negative number, lines were removed.
          *
          * 实现功能: 通知调试器已在编辑器中添加或删除行.这将导致调试器使断点列表与编辑器保持同步(即用户看到的内容).
          * 参数说明: editor 存在问题的编辑器.
          * 参数说明: startline 发生变化的起始行.
          * 参数说明: lines 添加或删除的行数.如果是正数,则添加行,如果是负数,则删除行.
          */
        virtual void EditorLinesAddedOrRemoved(cbEditor* editor, int startline, int lines);
    public:
        virtual void OnAttachReal() = 0;
        virtual void OnReleaseReal(bool appShutDown) = 0;

        virtual void SetupToolsMenu(wxMenu &menu) = 0;
        virtual bool ToolMenuEnabled() const;

        virtual bool SupportsFeature(cbDebuggerFeature::Flags flag) = 0;

        virtual cbDebuggerConfiguration* LoadConfig(const ConfigManagerWrapper &config) = 0;

        cbDebuggerConfiguration& GetActiveConfig();
        void SetActiveConfig(int index);
        int GetIndexOfActiveConfig() const;

        /**
           * 实现功能: Called when the user clicks OK in Settings -> Debugger...
           * 实现功能: 当用户在"设置"->"调试器"中单击"确定"时调用...
           */
        virtual void OnConfigurationChange(bool isActive) { wxUnusedVar(isActive); };

        /**
           * 实现功能: Start a new debugging process.
           * 实现功能: 启动新的调试过程.
           * */
        virtual bool Debug(bool breakOnEntry) = 0;

        /**
           * 实现功能: Continue running the debugged program.
           * 实现功能: 继续运行调试过的程序.
           */
        virtual void Continue() = 0;

        /**
           * 实现功能: Run the debugged program until it reaches the cursor at the current editor
           * 实现功能: 运行调试过的程序,直到它到达当前编辑器的光标处.
           * */
        virtual bool RunToCursor(const wxString& filename, int line, const wxString& line_text) = 0;

        /**
           * 实现功能: Sets the position of the Program counter to the specified filename:line
           * 实现功能: 将程序计数器的位置设置为指定的文件名:行
           */
        virtual void SetNextStatement(const wxString& filename, int line) = 0;

        /**
           * 实现功能: Execute the next instruction and return control to the debugger.
           * 实现功能: 执行下一条指令并将控件返回到调试器.
           */
        virtual void Next() = 0;

        /**
           * 实现功能: Execute the next instruction and return control to the debugger.
           * 实现功能: 执行下一条指令并将控件返回到调试器.
           */
        virtual void NextInstruction() = 0;

        /**
           * 实现功能: Execute the next instruction and return control to the debugger, if the instruction is a function call step into it.
           * 实现功能: 如果指令是进入调试器的函数调用步骤,则执行下一条指令并将控制返回给调试器.
           */
        virtual void StepIntoInstruction() = 0;

        /**
           * 实现功能: Execute the next instruction, stepping into function calls if needed, and return control to the debugger.
           * 实现功能: 执行下一条指令,根据需要单步执行函数调用,并将控制权返回给调试器.
           * */
        virtual void Step() = 0;

        /**
           * 实现功能: Execute the next instruction, stepping out of function calls if needed, and return control to the debugger.
           * 实现功能: 执行下一条指令,根据需要退出函数调用,并将控制权返回给调试器.
           */
        virtual void StepOut() = 0;

        /**
           * 实现功能: Break the debugging process (stop the debuggee for debugging).
           * 实现功能: 中断调试过程(停止调试对象进行调试).
           * */
        virtual void Break() = 0;

        /**
           * 实现功能: Stop the debugging process (exit debugging).
           * 实现功能: 停止调试过程(退出调试).
           * */
        virtual void Stop() = 0;

        /**
           * 实现功能: Is the plugin currently debugging?
           * 实现功能: 插件当前正在调试吗?
           * */
        virtual bool IsRunning() const = 0;

        /**
           * 实现功能: Is the plugin stopped on breakpoint?
           * 实现功能: 插件是否在断点处停止?
           * */
        virtual bool IsStopped() const = 0;

        /**
           * 实现功能: Is the plugin processing something?
           * 实现功能: 插件正在处理什么?
           */
        virtual bool IsBusy() const = 0;

        /**
           * 实现功能: Get the exit code of the last debug process.
           * 实现功能: 获取上一个调试进程的退出代码.
           * */
        virtual int GetExitCode() const = 0;

        // stack frame calls;
        // 堆栈帧调用
        virtual int GetStackFrameCount() const = 0;
        virtual cb::shared_ptr<const cbStackFrame> GetStackFrame(int index) const = 0;
        virtual void SwitchToFrame(int number) = 0;
        virtual int GetActiveStackFrame() const = 0;

        // breakpoints calls
        // 断点调用
        /**
           * 实现功能: Request to add a breakpoint.
          * 参数说明: file The file to add the breakpoint based on a file/line pair.
          * 参数说明: line The line number to put the breakpoint in @c file.
          * 返回值:  True if succeeded, false if not.
          *
           * 实现功能: 请求添加断点.
          * 参数说明: file 基于文件/行对添加断点的文件.
          * 参数说明: line 将断点放入参数file的行号.
          * 返回值:  如果成功则为真,否则为假.
          */
        virtual cb::shared_ptr<cbBreakpoint> AddBreakpoint(const wxString& filename, int line) = 0;

        /**
           * 实现功能: Request to add a breakpoint based on a data expression.
          * 参数说明: dataExpression The data expression to add the breakpoint.
          * 返回值:  True if succeeded, false if not.
          *
           * 实现功能: 基于数据表达式添加断点的请求.
          * 参数说明: dataExpression 要添加断点的数据表达式.
          * 返回值:  如果成功则为真,否则为假.
          */
        virtual cb::shared_ptr<cbBreakpoint> AddDataBreakpoint(const wxString& dataExpression) = 0;
        virtual int GetBreakpointsCount() const = 0;
        virtual cb::shared_ptr<cbBreakpoint> GetBreakpoint(int index) = 0;
        virtual cb::shared_ptr<const cbBreakpoint> GetBreakpoint(int index) const = 0;
        virtual void UpdateBreakpoint(cb::shared_ptr<cbBreakpoint> breakpoint) = 0;
        virtual void DeleteBreakpoint(cb::shared_ptr<cbBreakpoint> breakpoint) = 0;
        virtual void DeleteAllBreakpoints() = 0;
        virtual void ShiftBreakpoint(int index, int lines_to_shift) = 0;
        virtual void EnableBreakpoint(cb::shared_ptr<cbBreakpoint> breakpoint, bool enable) = 0;
        // threads
        // 线程数
        virtual int GetThreadsCount() const = 0;
        virtual cb::shared_ptr<const cbThread> GetThread(int index) const = 0;
        virtual bool SwitchToThread(int thread_number) = 0;

        // watches
        virtual cb::shared_ptr<cbWatch> AddWatch(const wxString& symbol) = 0;
        virtual void DeleteWatch(cb::shared_ptr<cbWatch> watch) = 0;
        virtual bool HasWatch(cb::shared_ptr<cbWatch> watch) = 0;
        virtual void ShowWatchProperties(cb::shared_ptr<cbWatch> watch) = 0;
        virtual bool SetWatchValue(cb::shared_ptr<cbWatch> watch, const wxString& value) = 0;
        virtual void ExpandWatch(cb::shared_ptr<cbWatch> watch) = 0;
        virtual void CollapseWatch(cb::shared_ptr<cbWatch> watch) = 0;
        virtual void UpdateWatch(cb::shared_ptr<cbWatch> watch) = 0;

        struct WatchesDisabledMenuItems
        {
            enum
            {
                Empty        = 0,
                Rename       = 1 << 0,
                Properties   = 1 << 1,
                Delete       = 1 << 2,
                DeleteAll    = 1 << 3,
                AddDataBreak = 1 << 4,
                ExamineMemory = 1 << 5
            };
        };

        /**
          * @param[out] disabledMenus A combination of WatchesDisabledMenuItems, which controls which of the default menu items are disabled
          * 参数[输出] disabledMenus是WatchesDisabledMenuItems的组合,它控制哪些默认菜单项被禁用
          */
        virtual void OnWatchesContextMenu(wxMenu &menu, const cbWatch &watch, wxObject *property, int &disabledMenus){
            wxUnusedVar(menu);
            wxUnusedVar(watch);
            wxUnusedVar(property);
            wxUnusedVar(disabledMenus);
        };

        virtual void SendCommand(const wxString& cmd, bool debugLog) = 0;

        virtual void AttachToProcess(const wxString& pid) = 0;
        virtual void DetachFromProcess() = 0;
        virtual bool IsAttachedToProcess() const = 0;

        virtual void GetCurrentPosition(wxString& filename, int &line) = 0;


        virtual void OnValueTooltip(const wxString& token, const wxRect &evalRect);
        virtual bool ShowValueTooltip(int style);
    private:
        void RegisterValueTooltip();
        void ProcessValueTooltip(CodeBlocksEvent& event);
        void CancelValueTooltip(CodeBlocksEvent& event);

    protected:
        enum StartType
        {
            StartTypeUnknown = 0,
            //运行
            StartTypeRun,
            //步进
            StartTypeStepInto
        };
    protected:
        virtual void ConvertDirectory(wxString& str, wxString base = _T(""), bool relative = true) = 0;
        virtual cbProject* GetProject() = 0;
        virtual void ResetProject() = 0;
        virtual void CleanupWhenProjectClosed(cbProject *project) = 0;

        /**
           * 实现功能: Called when the compilation has finished. The compilation is started when EnsureBuildUpToDate is called.
          * 参数说明: compilerFailed the compilation failed for some reason.
          * 参数说明: startType it is the same value given to the Debug method, when the debugger session was started.
          * 返回值:  True if debug session is start, false if there are any errors or the users canceled the session.
          *
           * 实现功能: 编译完成时调用.调用EnsureBuildUpToDate时开始编译.
          * 参数说明: compilerFailed 由于某种原因,编译失败.
          * 参数说明: startType 它与启动调试器会话时给调试方法的值相同.
          * 返回值:  如果启动调试会话,则为True如果有任何错误或用户取消了会话,则为false.
          *
        */
        virtual bool CompilerFinished(bool compilerFailed, StartType startType){
            wxUnusedVar(compilerFailed);
            wxUnusedVar(startType);
            return false;
        }
    public:
        //枚举调试窗体
        enum DebugWindows
        {
            //回溯
            Backtrace,
            //CPU寄存器
            CPURegisters,
            //反汇编
            Disassembly,
            //内存检测
            ExamineMemory,
            //线程
            Threads,
            //监视
            Watches
        };

        virtual void RequestUpdate(DebugWindows window) = 0;

    public:
        virtual wxString GetEditorWordAtCaret(const wxPoint *mousePosition = NULL);
        void ClearActiveMarkFromAllEditors();

        enum SyncEditorResult
        {
            SyncOk = 0,
            SyncFileNotFound,
            SyncFileUnknown
        };

        SyncEditorResult SyncEditor(const wxString& filename, int line, bool setMarker = true);

        void BringCBToFront();


        void ShowLog(bool clear);
        void Log(const wxString& msg, Logger::level level = Logger::info);
        void DebugLog(const wxString& msg, Logger::level level = Logger::info);
        bool HasDebugLog() const;
        void ClearLog();

        // Called only by DebuggerManager, when registering plugin or changing settings
        // 仅在注册插件或更改设置时由DebuggerManager调用
        void SetupLog(int normalIndex);

        wxString GetGUIName() const { return m_guiName; }
        wxString GetSettingsName() const { return m_settingsName; }

    protected:
        void SwitchToDebuggingLayout();
        void SwitchToPreviousLayout();

        bool GetDebuggee(wxString& pathToDebuggee, wxString& workingDirectory, ProjectBuildTarget* target);
        bool EnsureBuildUpToDate(StartType startType);
        bool WaitingCompilerToFinish() const { return m_WaitingCompilerToFinish; }

        int RunNixConsole(wxString& consoleTty);
        void MarkAsStopped();

    private:
        void OnEditorOpened(CodeBlocksEvent& event);
        void OnProjectActivated(CodeBlocksEvent& event);
        void OnProjectClosed(CodeBlocksEvent& event);
        void OnCompilerFinished(CodeBlocksEvent& event);
    private:
        wxString m_PreviousLayout;
        cbCompilerPlugin* m_pCompiler;
        bool m_WaitingCompilerToFinish;

        StartType m_StartType;

        int m_ActiveConfig;

        int m_LogPageIndex;
        bool m_lastLineWasNormal;
        wxString m_guiName, m_settingsName;
};

/**
  * 实现功能: Base class for tool plugins
  * This plugin is automatically managed by Code::Blocks, so the inherited
  * functions to build menus/toolbars are hidden.
  * Tool plugins are automatically added under the "Plugins" menu.
  *
  * 实现功能: 工具插件基类
  * 此插件由Code::Blocks自动管理,因此生成菜单/工具栏的继承函数被隐藏.工具插件会自动添加到"插件"菜单下.
  */
class PLUGIN_EXPORT cbToolPlugin : public cbPlugin
{
    public:
        cbToolPlugin();

        /**
           * 实现功能: Execute the plugin.
          *
          * This is the only function needed by a cbToolPlugin.
          * This will be called when the user selects the plugin from the "Plugins"
          * menu.
          *
          * 实现功能: 执行插件
          * 这是cbToolPlugin所需的唯一函数.当用户从"插件"菜单中选择插件时,将调用此函数
          */
        virtual int Execute() = 0;
    private:
        // "Hide" some virtual members, that are not needed in cbToolPlugin
        // "隐藏"一些cbToolPlugin中不需要的虚拟成员
        void BuildMenu(cb_unused wxMenuBar* menuBar){}
        void RemoveMenu(cb_unused wxMenuBar* menuBar){}
        void BuildModuleMenu(cb_unused const ModuleType type, cb_unused wxMenu* menu, cb_unused const FileTreeData* data = nullptr){}
        bool BuildToolBar(cb_unused wxToolBar* toolBar){ return false; }
        void RemoveToolBar(cb_unused wxToolBar* toolBar){}
};

/**
  * 实现功能: Base class for mime plugins
  * Mime plugins are called by Code::Blocks to operate on files that Code::Blocks
  * wouldn't know how to handle on itself.
  *
* 实现功能: mime插件的基类.Code::Blocks调用Mime插件来操作Code::Blocks不知道如何处理自身不识别的文件.
  */
class PLUGIN_EXPORT cbMimePlugin : public cbPlugin
{
    public:
        cbMimePlugin();

        /**
           * 实现功能: Can a file be handled by this plugin?
          * 参数说明: filename The file in question.
          * 返回值:  The plugin should return true if it can handle this file,false if not.
          *
           * 实现功能: 这个插件可以处理文件吗?
          * 参数说明: filename 有问题的文件.
          * 返回值:  如果插件能够处理这个文件,它应该返回true,否则返回false.
          *
          */
        virtual bool CanHandleFile(const wxString& filename) const = 0;

        /**
           * 实现功能: Open the file.
          * 参数说明: filename The file to open.
          * 返回值:  The plugin should return zero on success, other value on error.
          *
          * 实现功能: 打开文件
          * 参数说明: filename 要打开的文件.
          * 返回值: 插件成功时应返回0,错误时应返回其他值.
          */
        virtual int OpenFile(const wxString& filename) = 0;

        /**
          * 实现功能: Is this a default handler?
          * This is a flag notifying the main app that this plugin can handle
          * every file passed to it. Usually you 'll want to return false in
          * this function, because you usually create specialized handler
          * plugins (for specific MIME types)...
          *
          * 返回值:  True if this plugin can handle every possible MIME type,
          * false if not.
          *
          * 实现功能:这是默认处理程序吗?
          * 这是一个标志,通知主应用程序此插件可以处理传递给它的每个文件.
          * 通常您会希望在这个函数中返回false,因为您通常会创建专门的处理程序插件(用于特定的MIME类型)...
          * 返回值:  如果此插件可以处理所有可能的MIME类型,则为True否则为false.
          *
          */
        virtual bool HandlesEverything() const = 0;
    private:
        // "Hide" some virtual members, that are not needed in cbMimePlugin
        // "隐藏"一些虚拟成员,这些成员在cbMimePlugin中不需要
        void BuildMenu(cb_unused wxMenuBar* menuBar){}
        void RemoveMenu(cb_unused wxMenuBar* menuBar){}
        void BuildModuleMenu(cb_unused const ModuleType type, cb_unused wxMenu* menu, cb_unused const FileTreeData* data = nullptr){}
        bool BuildToolBar(cb_unused wxToolBar* toolBar){ return false; }
        void RemoveToolBar(cb_unused wxToolBar* toolBar){}
};

class wxHtmlLinkEvent;

/**
  * 实现功能: Base class for code-completion plugins
  * The main operations of a code-completion plugin are executed by CCManager
  * at the appropriate times. Smaller CC plugins *should* not have need to
  * register very many (if any) events/editor hooks.
  *
  * 实现功能: 代码完成插件的基类.
  * 代码自动补全插件的主要操作由CCManager在适当的时间执行.
  * 较小的CC插件应该不需要注册很多(如果有的话)事件/编辑器挂钩.
  *
  */
class PLUGIN_EXPORT cbCodeCompletionPlugin : public cbPlugin
{
    public:
        cbCodeCompletionPlugin();

        /** Level of functionality a CC plugin is able to provide.
         * CC插件能够提供的功能级别. */
        enum CCProviderStatus
        {
            //!< CC plugin provides no functionality.
            //!< CC插件不提供任何功能.
            ccpsInactive,
            //!< CC plugin provides specialized functionality.
            //!< CC插件提供了专门的功能.
            ccpsActive,
            //!< CC plugin provides generic functionality.
            //!< CC插件提供通用功能.
            ccpsUniversal
        };

        /** Structure representing a generic token, passed between CC plugins and CCManager.
         * 表示通用令牌的结构,在CC插件和CCManager之间传递.*/
        struct CCToken
        {
            /**
              * 实现功能: Convenience constructor.
              * Represents a generic token, passed between CC plugins and CCManager.
              * 参数说明: _id Internal identifier for a CC plugin to reference the token in its data structure.
              * 参数说明: dispNm The string CCManager will use to display this token.
              * 参数说明: categ The category corresponding to the index of the registered image (during autocomplete).
              *              Negative values are reserved for CCManager.
              *
              * 实现功能: 方便构造器.表示在CC插件和CCManager之间传递的通用令牌.
              * 参数说明: _id CC插件在其数据结构中引用令牌的内部标识符.
              * 参数说明: dispNm CCManager将使用字符串来显示此令牌.
              * 参数说明: categ 与注册图像索引相对应的类别(在自动完成期间).为CCManager保留负值.
              *
              */
            CCToken(int _id, const wxString& dispNm, int categ = -1) :
                id(_id), category(categ), weight(5), displayName(dispNm), name(dispNm) {}

            /**
              * 实现功能: Construct a fully specified CCToken.
              * Represents a generic token, passed between CC plugins and CCManager.
              * 参数说明: _id Internal identifier for a CC plugin to reference the token in its data structure.
              * 参数说明: dispNm The verbose string CCManager will use to display this token.
              * 参数说明: nm Minimal name of the token that CCManager may choose to display in restricted circumstances.
              * 参数说明: _weight Lower numbers are placed earlier in listing, 5 is default; try to keep 0-10.
              * 参数说明: categ The category corresponding to the index of the registered image (during autocomplete).
              *              Negative values are reserved for CCManager.
              *
              * 实现功能: 构造一个完全指定的CCToken.
              * 表示在CC插件和CCManager之间传递的通用令牌.
              * 参数说明: _id CC插件在其数据结构中引用令牌的内部标识符.
              * 参数说明: dispNm CCManager将使用详细字符串来显示此令牌.
              * 参数说明: nm Minimal CCManager在受限情况下可能选择显示的令牌的名称.
              * 参数说明: _weight 下面的数字放在清单的前面,5是默认值,尽量保持0-10.
              * 参数说明: categ 与注册图像索引相对应的类别(在自动完成期间).
              *              为CCManager保留负值.
              *
              */
            CCToken(int _id, const wxString& dispNm, const wxString& nm, int _weight, int categ = -1) :
                id(_id), category(categ), weight(_weight), displayName(dispNm), name(nm) {}

            //!< CCManager will pass this back unmodified. Use it as an internal identifier for the token.
            //!< CCManager将原封不动地传递这个消息.将其用作令牌的内部标识符.
            int id;
            //!< The category corresponding to the index of the registered image (during autocomplete).
            //!< 与注册图像索引相对应的类别(在自动完成期间).
            int category;
            //!< Lower numbers are placed earlier in listing, 5 is default; try to keep 0-10.
            //!< 下面的数字提前被放在列表项里面,5是默认值,尽量保持0-10.
            int weight;
            //!< 表示令牌的详细字符串.
            wxString displayName;
            //!< Minimal name of the token that CCManager may choose to display in restricted circumstances.
            //!< CCManager在受限情况下可以选择显示的令牌的最小名称.
            wxString name;
        };

        /** Structure representing an individual calltip with an optional highlighted range
         * 表示具有可选突出显示范围的单个调用提示的结构 */
        struct CCCallTip
        {
            /**
              * 实现功能: Convenience constructor.
              * Represents an individual calltip to be processed and displayed by CCManager.
              * 参数说明: tp The content of the calltip.
              *
              * 实现功能: 方便构造器.
              * 表示要由CCManager处理和显示的单个calltip.
              * 参数说明: tp 调用提示(calltip)的内容.
              *
              */
            CCCallTip(const wxString& tp) :
                hlStart(-1), hlEnd(-1), tip(tp) {}

            /**
              * 实现功能: Construct a calltip, specifying a highlighted range
              * Represents an individual calltip, containing a highlighted range (generally the
              * active parameter), to be processed and displayed by CCManager.
              * 参数说明: tp The content of the calltip.
              * 参数说明: highlightStart The start index of the desired highlighted range.
              * 参数说明: highlightEndThe end index of the desired highlighted range.
              *
              * 实现功能: 构造一个calltip,指定一个突出显示的范围
              * 表示要由CCManager处理和显示的单个调用提示,其中包含突出显示的范围(通常是活动参数).
              * 参数说明: tp 调用提示(calltip)的内容.
              * 参数说明: highlightStart 所需突出显示区域的起始索引.
              * 参数说明: highlightEndThe 所需突出显示区域的结束索引.
              *
              */
            CCCallTip(const wxString& tp, int highlightStart, int highlightEnd) :
                hlStart(highlightStart), hlEnd(highlightEnd), tip(tp) {}

            //!< The start index of the desired highlighted range.
            //!< 所需突出显示区域的起始索引.
            int hlStart;
            //!< The end index of the desired highlighted range.
            //!< 所需突出显示区域的结束索引.
            int hlEnd;
            //!< The content of the calltip.
            //!< 调用提示(calltip)的内容.
            wxString tip;
        };

        /**
          * 实现功能: Does this plugin handle code completion for the editor <tt>ed</tt>?
          * The plugin should check the lexer, the <tt>HighlightLanguage</tt>, the file extension,
          * or some combination of these. Do @em not call @c CCManager::GetProviderFor()
          * from this function.
          * 参数说明: ed The editor being checked.
          * 返回值:  The level of functionality this plugin is able to supply.
          *
          * 实现功能: 这个插件处理编辑器ed的代码完成吗?
          * 插件应该检查(司法解释器)lexer,(突出显示语言)HighlightLanguage,文件扩展名或它们的一些组合.
          * 参数@em请勿从此函数调用参数@c CCManager::GetProviderFor().
          * 参数说明: ed 正在检查的编辑器.
          * 返回值:  此插件能够提供的功能级别.
          *
          */
        virtual CCProviderStatus GetProviderStatusFor(cbEditor* ed) = 0;

        /**
          * 实现功能: Supply content for the autocompletion list.
          * CCManager takes care of calling this during most relevant situations. If the
          * autocompletion mechanism is required at a time that CCManager does not initiate, call
          * @code
          * CodeBlocksEvent evt(cbEVT_COMPLETE_CODE);
          * Manager::Get()->ProcessEvent(evt);
          * @endcode
          * In this case, the parameter isAuto is passed as false value.
          *
          * Here is an example
          * @code
          * #include <math.h>
          * int main()
          * {
          *     float i = cos|------auto completion here
          *               ^  ^
          * }
          * @endcode
          * This is the case the user has just enter the chars "cos", now to get a suggestion list.
          * The first '^' is the position of tknStart, and the second '^' is the position of tknEnd
          * In this case, the cc plugin would supply a CCToken vectors, which could contains "cos",
          * "cosh" and "cosh"...
          * In some special cases, the tknStart tknEnd may point to the same position, such as
          * @code
          * struct AAA { int m_aaa1; };
          * int main()
          * {
          *     AAA obj;
          *     obj.|------auto completion here
          *         ^
          * }
          * @endcode
          * Here, '^' are the positions of both tknStart and tknEnd.
          *
          * 参数说明: isAuto Passed as @c true if autocompletion was launched by typing an 'interesting'
          *               character such as '<tt>&gt;</tt>' (for '<tt>-&gt;</tt>'). It is the plugin's job
          *               to filter out incorrect calls of this.
          * 参数说明: ed The context of this codecompletion call.
          * @param[in,out] tknStart The assumed beginning of the token to be autocompleted. Change this variable
          *                         if the plugin calculates a different starting location.
          * @param[in,out] tknEnd The current position/end of the known part of the token to be completed. The
          *                       plugin is allowed to change this (but it is not recommended).
          * 返回值:  Completable tokens, or empty vector to cancel autocompletion.
          *
          * 实现功能: 提供自动完成列表的内容.
          * CCManager负责在最相关的情况下调用这个函数.如果在CCManager不启动时需要自动完成机制,请调用如下代码:
          * @code
          * CodeBlocksEvent evt(cbEVT_COMPLETE_CODE);
          * Manager::Get()->ProcessEvent(evt);
          * @endcode
          *
          * 在这种情况下,参数isAuto作为false值传递.
          *
          * 下面是一个例子代码
          * @code
          * #include <math.h>
          * int main()
          * {
          *     float i = cos|------此处自动完成(auto completion here)
          *               ^  ^
          * }
          * @endcode
          *
          * 这种情况下,用户只需输入字符"cos",现在就可以得到一个建议下拉列表列表.
          * 第一个“^”是tknStart的位置,第二个“^”是tknEnd的位置在本例中,CC插件将提供一个CCToken向量,它可以包含"cos","cosh"和"cosh"...
          * 在某些特殊情况下,tknEnd可以指向相同的位置,例如:
          * @code
          * struct AAA { int m_aaa1; };
          * int main()
          * {
          *     AAA obj;
          *     obj.|------此处自动完成(auto completion here)
          *         ^
          * }
          * @endcode
          * 这里,"^"是tknStart和tknEnd的位置.
          * 参数说明: isAuto 如果通过键入"有趣"字符(如">"(表示"—>")启动自动完成,则作为参数@c true传递.插件的工作是过滤掉不正确的调用.
          * 参数说明: ed 此代码自动补全调用的上下文.
          * 参数[入,出] tknStart 要自动完成的令牌的假定开头.如果插件计算不同的起始位置,请更改此变量.
          * 参数[入,出] tknEnd 要完成的令牌已知部分的当前位置/结尾.允许插件对此进行更改(但不建议这样做).
          * 返回值:  可完成的标记,或用于取消自动完成的空向量.
          *
          */
        virtual std::vector<CCToken> GetAutocompList(bool isAuto, cbEditor* ed, int& tknStart, int& tknEnd) = 0;

        /**
          * 实现功能: Supply html formatted documentation for the passed token.
          * Refer to http://docs.wxwidgets.org/stable/overview_html.html#overview_html_supptags for
          * the available formatting. When selecting colours, prefer use of the ones CCManager has
          * registered with ColourManager, which are (TODO: register colours). Returning an empty
          * string will cancel the documentation popup.
          * 参数说明: token The token to document.
          * 返回值:  Either an html document or an empty string (if no documentation available).
          *
          * 实现功能: 为传递的令牌提供html格式的文档.
          * 有关可用格式,请参阅http://docs.wxwidgets.org/stable/overview_html.html#overview_html_supptags.
          * 选择颜色时,请优先使用代码自动补全管理器(CCManager)在颜色管理器(ColorManager)中注册的颜色(TODO:注册颜色).
          * 返回空字符串将取消文档弹出窗口.
          * 参数说明: token 要记录的令牌.
          * 返回值:  html文档或空字符串(如果没有可用的文档).
          *
          */
        virtual wxString GetDocumentation(const CCToken& token) = 0;

        /**
          * 实现功能: Supply content for the calltip at the specified location.
          * The output parameter @c argsPos is required to be set to the same (but unique) position
          * for each unique calltip. This position is the location corresponding to the beginning of
          * the argument list:
          * @code
          * int endOfWord = stc->WordEndPosition(pos, true);
          *                                     ^
          * @endcode
          * Each returned CCCallTip is allowed to have embedded '\\n' line breaks.
          *
          * 参数说明: pos The location in the editor that the calltip is requested for.
          * 参数说明: style The scintilla style of the cbStyledTextCtrl at the given location. (TODO: This
          *              is unusual, remove it?)
          * 参数说明: ed The context of this calltip request.
          * @param[out] argsPos The location in the editor of the beginning of the argument list. @em Required.
          * 返回值:  Each entry in this vector is guaranteed either a new line or a separate page in the calltip.
          *         CCManager will decide if lines should be further split (for formatting to fit the monitor).
          *
          * 实现功能: 在指定位置提供呼叫提示(calltip)的内容.
          * 对于每个唯一的呼叫提示(calltip),输出参数@c argsPos必须设置为相同(但唯一)的位置.
          * 此位置是与参数列表开头相对应的位置：
          * @code
          * int endOfWord = stc->WordEndPosition(pos, true);
          * @endcode
          * 每个返回的CCCallTip都允许有嵌入的'\\n'换行符.
          * 参数说明: pos 编辑器中请求调用提示的位置.
          * 参数说明: style 给定位置处cbStyledTextCtrl的闪烁样式.(TODO:这是不寻常的,移除它?)
          * 参数说明: ed 此呼叫提示(calltip)请求的上下文.
          * 参数[出] argsPos 参数列表开头在编辑器中的位置.需要参数@em.
          * 返回值:  这个容器(向量)中的每个条目都保证在呼叫提示(calltip)中有一个新行或一个单独的页面.
          * 代码自动补全管理器(CCManager)将决定是否应该进一步拆分行(以便格式化以适合监视器).
          *
          */
        virtual std::vector<CCCallTip> GetCallTips(int pos, int style, cbEditor* ed, int& argsPos) = 0;

        /**
          * 实现功能: Supply the definition of the token at the specified location.
          * The token(s) returned by this function are used to display tooltips.
          * 参数说明: pos The location being queried.
          * 参数说明: ed The context of the request.
          * @param[out] allowCallTip Allow CCManager to consider displaying a calltip if the results from this
          *                          function are unsuitable/empty. True by default.
          * 返回值:  A list of the token(s) that match the specified location, an empty vector if none.
          *
          * 实现功能: 在指定位置提供令牌的定义.
          * 此函数返回的令牌用于显示工具提示.
          * 参数说明: pos 正在查询的位置.
          * 参数说明: ed 请求的上下文(编辑器).
          * 参数[出] allowCallTip 如果此函数的结果不合适/为空,则允许CCManager考虑显示调用提示.默认情况下为True.
          * 返回值:  与指定位置匹配的令牌列表,如果没有则为空容器(向量).
          *
          */
        virtual std::vector<CCToken> GetTokenAt(int pos, cbEditor* ed, bool& allowCallTip) = 0;

        /**
         * 实现功能: Callback to handle a click on a link in the documentation popup.
         * Handle a link command by, for example, showing the definition of a member function, or opening
         * an editor to the location of the declaration.
         * 参数说明: event The generated event (it is the plugin's responsibility to Skip(), if desired).
         * @param[out] dismissPopup If set to true, the popup will be hidden.
         * 返回值:  If non-empty, the popup's content will be set to this html formatted string.
         *
         * 实现功能: 回调以处理在文档弹出窗口中单击链接的操作.
         * 例如,通过显示成员函数的定义或打开声明位置的编辑器来处理链接命令.
         * 参数说明: event 生成的事件(如果需要,插件的责任是Skip()).
         * 参数[出] dismissPopup 如果设置为true,弹出窗口将被隐藏.
         * 返回值:  如果非空,弹出窗口的内容将设置为此html格式的字符串.
         *
         */
        virtual wxString OnDocumentationLink(wxHtmlLinkEvent& event, bool& dismissPopup) = 0;

        /**
          * 实现功能: Callback for inserting the selected autocomplete entry into the editor.
          * The default implementation executes (wx)Scintilla's insert. Override and call
          * @c ed->GetControl()->AutoCompCancel() for different @c wxEVT_SCI_AUTOCOMP_SELECTION behaviour.
          * 参数说明: token The CCToken corresponding to the selected entry.
          * 参数说明: ed The editor to operate in.
          *
          * 实现功能: 用于将选定的自动完成项插入编辑器的回调.
          * 默认实现执行(wx)闪烁体的插入.重写并调用参数@c ed->GetControl()->AutoCompCancel(),以实现不同的参数@c wxEVT_SCI_AUTOCOMP_SELECTION行为.
          * 参数说明: token 与选定项对应的CCToken.
          * 参数说明: ed 要在其中操作的编辑器.
          *
          */
        virtual void DoAutocomplete(const CCToken& token, cbEditor* ed);

        /**
          * 实现功能: Callback for inserting the selected autocomplete entry into the editor.
          * This function is only called if CCManager fails to retrieve the CCToken associated with the
          * selection (which should never happen). The default implementation creates a CCToken and passes
          * it to <tt>DoAutocomplete(const CCToken&, cbEditor*)</tt><br>
          * Override for different behaviour.
          * 参数说明: token A string corresponding to the selected entry.
          * 参数说明: ed The editor to operate in.
          *
          * 实现功能: 用于将选定的自动完成项插入编辑器的回调.
          * 只有当CCManager检索不到与所选内容相关联的CCToken时(这种情况永远不会发生),才会调用此函数.
          * 默认实现创建一个CCToken并将其传递给DoAutocomplete(const CCToken&,cbEditor*)覆盖,以实现不同的行为.
          * 参数说明: token 与选定项对应的字符串.
          * 参数说明: ed 要在其中操作的编辑器.
          *
          */
        virtual void DoAutocomplete(const wxString& token, cbEditor* ed);

    protected:
        /**
          * 实现功能: Has this plugin been selected to provide content for the editor.
          * Convenience function; asks CCManager if this plugin is granted jurisdiction over the editor.
          * 参数说明: ed The editor to check.
          * 返回值:  Is provider for the editor.
          *
          * 实现功能: 是否已选择此插件为编辑器提供内容.
          * 便利功能,询问CCManager该插件是否被授予对编辑器的管辖权.
          * 参数说明: ed 检查的编辑器.
          * 返回值:  是编辑器的提供程序.
          *
          */
        bool IsProviderFor(cbEditor* ed);
};

/**
  * 实现功能: Base class for wizard plugins
  * Wizard plugins are called by Code::Blocks when the user selects
  * "File->New...".
  * A plugin of this type can support more than one wizard. Additionally,
  * each wizard can support new workspaces, new projects, new targets or new files.
  * The @c index used as a parameter to most of the functions, denotes 0-based index
  * of the project wizard to run.
  *
  * 实现功能: 向导插件的基类
  * 当用户选择"文件->新建..."时,向导插件由Code::Blocks调用.
  * 这种类型的插件可以支持多个向导.此外,每个向导都可以支持新工作区,新项目,新目标或新文件.
  * 参数@c index用作大多数函数的参数,表示要运行的项目向导的基于0的索引.
  *
  */
class PLUGIN_EXPORT cbWizardPlugin : public cbPlugin
{
    public:
        cbWizardPlugin();

        /**
         * 返回值:  the number of template wizards this plugin contains
         * 返回值:  此插件包含的模板向导数
         */
        virtual int GetCount() const = 0;

        /**
         * 参数说明: index the wizard index.
         * 返回值:  the output type of the specified wizard at @c index
         *
         * 参数说明: index 向导索引.
         * 返回值:  参数(@c index)索引处指定向导的输出类型
         *
         */
        virtual TemplateOutputType GetOutputType(int index) const = 0;

        /**
         * 参数说明: index the wizard index.
         * 返回值:  the template's title
         *
         * 参数说明: index 向导索引.
         * 返回值:  模板标题
         *
         */
        virtual wxString GetTitle(int index) const = 0;

        /**
         * 参数说明: index the wizard index.
         * 返回值:  the template's description
         *
         * 参数说明: index 向导索引.
         * 返回值:  模板描述
         *
         */
        virtual wxString GetDescription(int index) const = 0;

        /**
         * 参数说明: index the wizard index.
         * 返回值:  the template's category (GUI, Console, etc; free-form text). Try to adhere to standard category names...
         *
         * 参数说明: index 向导索引.
         * 返回值:  模板的类别(GUI,控制台等自由格式文本).尝试坚持标准类别名称...
         *
        */
        virtual wxString GetCategory(int index) const = 0;

        /**
         * 参数说明: index the wizard index.
         * 返回值:  the template's bitmap
         *
         * 参数说明: index 向导索引.
         * 返回值:  模板的位图
         *
        */
        virtual const wxBitmap& GetBitmap(int index) const = 0;

        /**
         * 参数说明: index the wizard index.
         * 返回值:  this wizard's script filename (if this wizard is scripted).
         *
         * 参数说明: index 向导索引.
         * 返回值:  此向导的脚本文件名(如果此向导已编写脚本).
         *
        */
        virtual wxString GetScriptFilename(int index) const = 0;

        /**
          * When this is called, the wizard must get to work ;).
          * 参数说明: index the wizard index.
          * 参数说明: createdFilename if provided, on return it should contain the main filename
          *                         this wizard created. If the user created a project, that
          *                         would be the project's filename.
          *                         If the wizard created a build target, that would be an empty string.
          *                         If the wizard created a file, that would be the file's name.
          * 返回值:  a pointer to the generated cbProject or ProjectBuildTarget. NULL for everything else (failure too).
          * You should dynamic-cast this to the correct type based on GetOutputType() 's value.
          *
          * 实现功能:向导启动命令,调用此命令时,向导必须开始工作.
          * 参数说明: index 向导索引.
          * 参数说明: createdFilename 如果提供,则返回时应包含此向导创建的主文件名.
          * 如果用户创建了一个项目,那将是该项目的文件名.
          * 如果向导创建了一个构建目标,那将是一个空字符串.
          * 如果向导创建了一个文件,那就是该文件的名称.
          * 返回值:指向生成的cbProject或ProjectBuildTarget的指针.其他的都是空的(失败也一样).
          * 您应该根据GetOutputType()的值将其动态转换为正确的类型.
          *
         */
        // do your work ;)
        // 做你的工作
        virtual CompileTargetBase* Launch(int index, wxString* createdFilename = nullptr) = 0;
    private:
        // "Hide" some virtual members, that are not needed in cbCreateWizardPlugin
        // "隐藏"cbCreateWizardPlugin中不需要的一些虚拟成员
        void BuildMenu(cb_unused wxMenuBar* menuBar){}
        void RemoveMenu(cb_unused wxMenuBar* menuBar){}
        void BuildModuleMenu(cb_unused const ModuleType type, cb_unused wxMenu* menu, cb_unused const FileTreeData* data = nullptr){}
        bool BuildToolBar(cb_unused wxToolBar* toolBar){ return false; }
        void RemoveToolBar(cb_unused wxToolBar* toolBar){}
};

/**
  * 实现功能: Base class for SmartIndent plugins
  * SmartIndent plugins provide the smart indenting for different languages.
  * These plugins don't eat processing time after startup when they are not active.
  * The hook gets installed during OnAttach.
  *
  * 实现功能: 智能缩进(SmartIndent)插件的基类
  * SmartIndent插件为不同的语言提供了智能缩进.
  * 当这些插件不活动时,它们不会占用启动后的处理时间.
  * 钩子在插件附加事件执行(OnAttach)期间安装.
  *
  */
class cbStyledTextCtrl;
class cbSmartIndentPlugin : public cbPlugin
{
    public:
        cbSmartIndentPlugin();
    private:
        // "Hide" some virtual members, that are not needed in cbSmartIndentPlugin
        // "隐藏"一些虚拟成员,这在cbSmartIndentPlugin中是不需要的
        void BuildMenu(cb_unused wxMenuBar* menuBar){}
        void RemoveMenu(cb_unused wxMenuBar* menuBar){}
        void BuildModuleMenu(cb_unused const ModuleType type, cb_unused wxMenu* menu, cb_unused const FileTreeData* data = nullptr){}
        bool BuildToolBar(cb_unused wxToolBar* toolBar){ return false; }
        void RemoveToolBar(cb_unused wxToolBar* toolBar){}
    protected:
        void OnAttach();
        void OnRelease(bool appShutDown);

    public:
        /**
          * When this is called, the smartIndent mechanism must get to work ;).
          * Please check if this is the right smartIndent mechanism first:
          * Don't indent for languages you don't know.
          *
          * 实现功能:勾住编辑器,调用时,smartIndent机制必须开始工作.
          * 请先检查这是否是正确的智能缩进机制:
          * 不要缩进不懂的语言.
          *
          */
        virtual void OnEditorHook(cbEditor* editor, wxScintillaEvent& event) const = 0;

        /**
          * This is called after a code completion operation finishes.
          * Use it as an opportunity to tidy up CC's formating.
          * Don't indent for languages you don't know.
          *
          * 实现功能:这是在代码完成操作完成后调用的.
          * 利用这个机会整理CC的格式.
          * 不要缩进不懂的语言.
          *
          */
        virtual void OnCCDone(cb_unused cbEditor* ed){}

    protected:
        /**
         * (reverse) search for the last word which is not comment
         * (反向)搜索最后一个没有注释的单词
        **/
        wxString GetLastNonCommentWord(cbEditor* ed, int position = -1, unsigned int NumberOfWords = 1 ) const;
        /**
         * (reverse) search for the last characters, which are not whitespace and not comment
         * (反向)搜索最后一个字符,这些字符不是空格,也不是注释
         **/
        wxString GetLastNonWhitespaceChars(cbEditor* ed, int position = -1, unsigned int NumberOfChars = 1) const;

        /**
         * forward search to the next character which is not a whitespace
         * 将搜索转发到下一个非空白字符
         **/
        wxChar GetLastNonWhitespaceChar(cbEditor* ed, int position = -1) const;
        wxChar GetNextNonWhitespaceCharOnLine(cbStyledTextCtrl* stc, int position = -1, int *pos = nullptr) const;

        int FindBlockStart(cbStyledTextCtrl* stc, int position, wxChar blockStart, wxChar blockEnd, bool skipNested = true) const;
        int FindBlockStart(cbStyledTextCtrl* stc, int position, wxString blockStart, wxString blockEnd, bool CaseSensitive = true) const;

        void Indent(cbStyledTextCtrl* stc, wxString& indent)const;
        bool Indent(cbStyledTextCtrl* stc, wxString& indent, int posInLine)const;

        /**
         * Get the first brace in the line according to the line style
         * 根据线条样式获取线条中的第一个大括号
         */
        int GetFirstBraceInLine(cbStyledTextCtrl* stc, int string_style)const;

        /**
         * Get the last non-whitespace character from position in line
         * 从行中的位置获取最后一个非空白字符
         */
        wxChar GetNextNonWhitespaceCharOfLine(cbStyledTextCtrl* stc, int position = -1, int *pos = nullptr)const;
        bool AutoIndentEnabled()const;
        bool SmartIndentEnabled()const;
        bool BraceSmartIndentEnabled()const;
        bool BraceCompletionEnabled()const;
        bool SelectionBraceCompletionEnabled()const;
        void OnCCDoneEvent(CodeBlocksEvent& event);
    private:
        int m_FunctorId;//仿函数编号?
};

/**
  * 实现功能: Plugin registration object.
  * Use this class to register your new plugin with Code::Blocks.
  * All you have to do is instantiate a PluginRegistrant object.
  * @par
  * Example code to use in one of your plugin's source files (supposedly called "MyPlugin"):
  * @code
  * namespace
  * {
  *     PluginRegistrant<MyPlugin> registration("MyPlugin");
  * }
  * @endcode
  *
  * 实现功能: 插件注册对象.
  * 使用此类向Code::Blocks注册新插件.
  * 你所要做的就是实例化一个PluginRegistrant对象.
  * 参数:
  * 在插件的源文件中使用的示例代码(假定称为"MyPlugin"):
  * @code
  * namespace
  * {
  *     PluginRegistrant<MyPlugin> registration("MyPlugin");
  * }
  * @endcode
  *
  */
template<class T> class PluginRegistrant
{
    public:
        /// @param name The plugin's name.
        /// 参数 name 插件的名称.
        PluginRegistrant(const wxString& name)
        {
            // name:插件名称
            // CreatePlugin:创建
            // FreePlugin:销毁
            // SDKVersion: SDK版本
            Manager::Get()->GetPluginManager()->RegisterPlugin(name,&CreatePlugin,&FreePlugin,&SDKVersion);
        }

        static cbPlugin* CreatePlugin()
        {
            return new T;
        }

        static void FreePlugin(cbPlugin* plugin)
        {
            delete plugin;
        }

        static void SDKVersion(int* major, int* minor, int* release)
        {
            if (major) *major = PLUGIN_SDK_VERSION_MAJOR;
            if (minor) *minor = PLUGIN_SDK_VERSION_MINOR;
            if (release) *release = PLUGIN_SDK_VERSION_RELEASE;
        }
};

#endif // CBPLUGIN_H
